package db

import (
	"ai-gateway/config"
	"fmt"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

var DB *sqlx.DB

// InitDB 简化版数据库初始化：存在则连接，不存在则创建
func InitDB() error {
	// 1. 构建完整DSN（包含数据库名）
	fullDSN := fmt.Sprintf(
		"%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=true",
		config.Config.DBUser,
		config.Config.DBPassword,
		config.Config.DBHost,
		config.Config.DBPort,
		config.Config.DBName,
	)

	// 2. 尝试直接连接目标数据库（如果存在）
	var err error
	DB, err = sqlx.Connect("mysql", fullDSN)
	if err == nil {
		setDBPoolConfig(DB)
		fmt.Printf("数据库 %s 已存在，连接成功\n", config.Config.DBName)
		return nil
	}

	// 3. 数据库不存在，连接服务器创建数据库
	baseDSN := fmt.Sprintf(
		"%s:%s@tcp(%s:%s)/?charset=utf8mb4", // 不指定数据库名
		config.Config.DBUser,
		config.Config.DBPassword,
		config.Config.DBHost,
		config.Config.DBPort,
	)

	// 连接MySQL服务器（无数据库）
	baseDB, err := sqlx.Connect("mysql", baseDSN)
	if err != nil {
		return fmt.Errorf("连接数据库服务器失败: %v", err)
	}
	defer baseDB.Close()

	// 创建数据库
	createStmt := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", config.Config.DBName)
	if _, err := baseDB.Exec(createStmt); err != nil {
		return fmt.Errorf("创建数据库失败: %v", err)
	}
	fmt.Printf("数据库 %s 创建成功\n", config.Config.DBName)

	// 4. 连接新创建的数据库
	DB, err = sqlx.Connect("mysql", fullDSN)
	if err != nil {
		return fmt.Errorf("连接新数据库失败: %v", err)
	}

	// 5. 执行初始化脚本（创建表和基础数据）
	if err := executeInitScript(DB); err != nil {
		DB.Close()
		return fmt.Errorf("执行初始化脚本失败: %v", err)
	}

	// 配置连接池
	setDBPoolConfig(DB)
	fmt.Println("数据库初始化完成并连接成功")
	return nil
}

// setDBPoolConfig 配置连接池
func setDBPoolConfig(db *sqlx.DB) {
	db.SetMaxOpenConns(20)
	db.SetMaxIdleConns(10)
	db.SetConnMaxLifetime(30 * time.Minute)
}

// executeInitScript 执行初始化脚本（创建表结构和基础数据）
func executeInitScript(db *sqlx.DB) error {
	// 获取脚本路径（与db.go同目录）
	_, currentFile, _, ok := runtime.Caller(0)
	if !ok {
		return fmt.Errorf("无法获取当前文件路径")
	}
	scriptPath := filepath.Join(filepath.Dir(currentFile), "init.sql")

	// 读取脚本内容
	content, err := os.ReadFile(scriptPath)
	if err != nil {
		return fmt.Errorf("读取脚本失败: %v（路径: %s）", err, scriptPath)
	}

	// 执行脚本（拆分语句执行，避免格式问题）
	scripts := splitSQL(string(content))
	for _, sql := range scripts {
		if sql = trimSQL(sql); sql == "" {
			continue
		}
		if _, err := db.Exec(sql); err != nil {
			return fmt.Errorf("执行SQL失败: %v（语句: %s）", err, sql)
		}
	}

	fmt.Println("初始化脚本执行成功")
	return nil
}

// 辅助函数：拆分SQL语句
func splitSQL(sql string) []string {
	return strings.Split(sql, ";")
}

// 辅助函数：清理SQL语句中的空白和特殊字符
func trimSQL(sql string) string {
	sql = strings.TrimSpace(sql)
	sql = strings.ReplaceAll(sql, "\r\n", "\n") // 统一换行符
	return sql
}
